package com.telife.interfacesecurity.interceptor;

import com.telife.interfacesecurity.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author york
 * @since 2020/3/21
 */
@Component
public class ReqIntercepter implements HandlerInterceptor {

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //当前时间戳
        long nowTimeStamp = System.currentTimeMillis();
        //请求方的Ip地址
        String ip = request.getRemoteAddr();
        //redis里的请求方Ip的信息值
        String existIpValue = redisUtil.getStrKey(ip);
        //Ip黑名单列表
        List<String> ipBlackList = redisUtil.getListKey("IpBlackList");
        //检测黑名单是否有该Ip
        if(!ipBlackList.isEmpty()){
            for(String blackIpStr : ipBlackList){
                //黑名单Ip
                String blackIp = blackIpStr.substring(0,blackIpStr.indexOf("::"));
                //黑名单创建时间
                long createTime = Long.valueOf(blackIpStr.substring(blackIpStr.indexOf("::")+2));
                //两个时间戳相隔的时长（秒）
                long interval = (nowTimeStamp - createTime)/1000;
                //如果时间间隔小于1天，则说明还在黑名单有效期内，否则就删除该元素
//                if(interval <= 86400){
                if(interval <= 60){
                    request.getRequestDispatcher("/interface/warning").forward(request,response);
                    return false;
                }
                else if(interval > 60){
                    synchronized (this){
                        //移除元素
                        redisUtil.removeListElement("IpBlackList",blackIpStr);
                    }
                    return true;
                }
            }
        }
        //如果redis没有此Ip，则往redis存入此ip
        if(existIpValue == null){
            //value值由请求次数和时间戳组成
            String value = String.format("%s:%s",1,System.currentTimeMillis());
            synchronized (this){
                //有效期为1天，过期自动删除
                redisUtil.setStrKey(ip,value,1, TimeUnit.DAYS);
            }
            return true;
        }
        //如果redis里存在此Ip，
        if(existIpValue != null){
            //累计连续请求的次数
            int count = Integer.valueOf(existIpValue.substring(0,existIpValue.indexOf(":")));
            //最新一次连续请求的时间戳
            long reqTimeStamp =Long.valueOf(existIpValue.substring(existIpValue.indexOf(":")+1));
            //两个时间戳相隔的时长（秒）
            long interval = (nowTimeStamp - reqTimeStamp)/1000;
            //如果3秒内重复请求，则增加计数
            if(interval <= 3){
                synchronized (this){
                    count += 1;
                    String updateValue = String.format("%s:%s",count,System.currentTimeMillis());
                    redisUtil.updateStrValue(ip,updateValue);
                }
            }
            //如果时3秒之后的，只更新请求时间
            else if(interval > 3){
                String updateValue = String.format("%s:%s",count,System.currentTimeMillis());
                redisUtil.updateStrValue(ip,updateValue);
            }
            //如果累计连续请求的次数超过5次，则列入黑名单,并删除以此Ip为Key的键
            if(count > 5){
                //黑名单Ip由ip和时间戳组成,使用"::"分隔
                String blackIp = String.format("%s::%s",ip,nowTimeStamp);
                synchronized (this){
                    redisUtil.setListKey("IpBlackList",blackIp);
                    redisUtil.deleteKey(ip);
                }
                request.getRequestDispatcher("/interface/warning").forward(request,response);
                return false;
            }
            return true;
        }
        request.getRequestDispatcher("/interface/error").forward(request,response);
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {

    }
}
